﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Security.Cryptography;
using System.Text;
using CommonFramework.Time;

namespace CommonFramework.Log
{
    internal struct LogMessageData
    {
        public DateTime GeneratedTime { get; private set; }
        public LogSeverity Severity { get; private set; }
        public string RawContent { get; private set; }
        /// <summary>
        /// 日志信息附带的参考对象,默认为空.如发生异常错误的日志,Context可为异常Exception对象
        /// </summary>
        public object Context { get; private set; }

        public LogMessageData(string content, LogSeverity severity = LogSeverity.Info,object context=null)
        {
            this.Severity = severity;
            this.GeneratedTime = DateTime.Now;
            this.RawContent = content;
            this.Context = context;
        }
    }

    public class LogMessage : IEqualityComparer<LogMessage>
    {
        public DateTime GeneratedTime => _data.GeneratedTime;
        public object Context => _data.Context;
        public LogSeverity Severity
        {
            get
            {
                if (_modifier != null)
                    return _modifier.Severity;
                else
                    return _data.Severity;
            }
        }

        //如果有Modifier,则优先使用Modifier中的内容
        private readonly LogMessageModifier _modifier;
        private readonly LogMessageData _data;

        internal LogMessage(LogMessageData data)
        {
            this._data = data;
            this._modifier = new LogMessageModifier(data);
            this._refreshHashCode = true;
        }

        public string GetContent()
        {
            if (_modifier != null)
            {
                var (head, content) = _modifier.GetMessage();
                return $"{head} {content}";
            }
            else
            {
                return _data.RawContent;
            }
        }

        public override string ToString() => GetContent();

        public int Length() => GetContent().Length;

        public LogMessageModifier GetModifier()
        {
            _refreshHashCode = true;
            return _modifier;
        }

        #region 哈希相等性

        public bool Equals(LogMessage x, LogMessage y)
        {
            if ((x == null) ^ (y == null)) //其中一个为null,一个不为null
                return false;
            else if (x == null) //两个都为null
                return true;
            else
                return x.GetHashCode() == y.GetHashCode();
        }
        private int _cacheHashCode;
        private bool _refreshHashCode;
        public int GetHashCode(LogMessage obj)
        {
            if (obj._refreshHashCode)
            {
                int h1= obj.Severity.GetHashCode();
                int h2 = obj.GetContent().GetHashCode();
                int h = HashUtil.CombineHashCodes(h1, h2);
                if (obj.Context != null)
                    h = HashUtil.CombineHashCodes(h, obj.Context.GetHashCode());

                obj._cacheHashCode = h;
                obj._refreshHashCode = false;
            }
            return obj._cacheHashCode;
        }

        public override bool Equals(object obj)
        {
            return Equals(this, obj);
        }
        public override int GetHashCode()
        {
            return GetHashCode(this);
        }

        #endregion
    }
}